import type { YmCssMotionProps } from '@/YmCssMotion';

export type Key = string;
export type IconType =
  | React.ReactNode
  | ((props: YmDataNode) => React.ReactNode);

export interface YmDataNode {
  showCheckableBox?: boolean;
  disabled?: boolean;
  disableCheckbox?: boolean;
  icon?: IconType;
  isLeaf?: boolean; //配合loadData使用
  selectable?: boolean;
  key?: string;
  title?: React.ReactNode | ((data: YmDataNode) => React.ReactNode);
  children?: YmDataNode[];
  [propName: string]: any;
}

//---------------
export interface FieldNames {
  title?: string;
  key?: string;
  children?: string;
}

export type DraggableFn = (node: YmDataNode) => boolean;
export type DraggableConfig = {
  icon?: React.ReactNode | false;
  nodeDraggable?: DraggableFn;
};

type motionConfig = Omit<YmCssMotionProps, 'children' | 'visible'>;

export type NodeDragAndRopEventParams = {
  event: React.DragEvent;
  node: YmDataNode;
  dragNode?: YmDataNode;
};

export type OnCheckInfo = {
  checked: boolean;
  node: YmDataNode;
  checkedNodes: YmDataNode[];
  nativeEvent: MouseEvent;
  halfCheckedKeys: Key[];
};
export type OnSelectInfo = {
  selected: boolean;
  node: YmDataNode;
  selectedNodes: YmDataNode;
  nativeEvent: MouseEvent;
};

export interface YmTreeProps {
  prefixCls?: string; //ym-tree
  rootClassName?: string; //ym-tree-treenode
  rootStyle?: React.CSSProperties;
  treeNodeClassName?: string;
  treeNodeStyle?: React.CSSProperties;
  nodeContentWrapperClassName?: string; //ym-tree-node-content-wrapper
  nodeContentWrapperStyle?: React.CSSProperties;
  indentWidth?: number;
  treeData: YmDataNode[];
  fieldNames?: FieldNames;
  icon?: IconType;
  showLine?: boolean;
  switcherIcon?: React.ReactNode;
  multiple?: boolean;

  treeShowCheckableBox?: boolean; //是否显示checkbox框
  disabled?: boolean; //disabled时，不计入expendKeys,无法onselect,oncheck
  treeSelectable?: boolean;

  draggable?: DraggableFn | boolean | DraggableConfig;
  cannotDrop?: (node: YmDataNode) => boolean;
  motion?: motionConfig;

  defaultExpandParent?: boolean; //默认展开父节点,非受控
  autoExpandParent?: boolean; //是否自动展开父节点,受控

  defaultExpandAll?: boolean;
  defaultExpandedKeys?: Key[];
  expandedKeys?: Key[];

  defaultCheckedKeys?: Key[];
  checkedKeys?: Key[];
  defaultSelectedKeys?: Key[];
  selectedKeys?: Key[];

  titleRender?: (node: YmDataNode) => React.ReactNode;
  onExpand?: (
    expandedKeys: Key[],
    info: {
      node: YmDataNode;
      expanded: boolean;
      nativeEvent: MouseEvent;
    },
  ) => void;
  // onLoad?: ( //节点加载完毕时触发
  //   loadedKeys: Key[],
  //   info: {
  //     event: 'load';
  //     node: YmDataNode;
  //   },
  // ) => void;
  loadData?: (treeNode: YmDataNode) => Promise<unknown>; //异步加载数据的函数
  // loadedKeys?:Key[]; // （受控）已经加载的节点，需要配合 loadData 使用

  onCheck?: (checkedKeys: Key[], info: OnCheckInfo) => void;
  onSelect?: (selectedKeys: Key[], info: OnSelectInfo) => void;
  onDragStart?: (info: NodeDragAndRopEventParams) => void;
  onDragEnter?: (info: NodeDragAndRopEventParams) => void;
  onDragOver?: (info: NodeDragAndRopEventParams) => void;
  onDragLeave?: (info: NodeDragAndRopEventParams) => void;
  onDrop?: (info: NodeDragAndRopEventParams) => void;
  onDragEnd?: (info: NodeDragAndRopEventParams) => void;
}

interface InternalDataNode {
  showCheckableBox?: boolean;
  disabled?: boolean;
  disableCheckbox?: boolean;
  icon?: IconType;
  isLeaf?: boolean;
  selectable?: boolean;
  key: Key;
  title: React.ReactNode | ((data: YmDataNode) => React.ReactNode);
}

export interface InternalDataNodeForDataMap
  extends Omit<InternalDataNode, 'title'> {
  level: number;
  pos: string;
  index: number;
  node: YmDataNode;
  nodes: YmDataNode[];
  children?: InternalDataNodeForDataMap[];
  parent?: InternalDataNodeForDataMap;
}

export interface InternalFlattenNode {
  title: React.ReactNode | ((data: YmDataNode) => React.ReactNode);
  key: Key;
  parent?: InternalFlattenNode;
  children?: InternalFlattenNode[];
  pos: string;
  data: YmDataNode;
  isStart: boolean[];
  isEnd: boolean[];
}

export interface NodeListProps {
  data: InternalFlattenNode[];
  motion: motionConfig;
  expandedKeys: Key[];
  loadingKeys: Key[];
  loadedKeys: Key[];
  checkedKeys: Key[];
  halfCheckedKeys: Key[];
  selectedKeys: Key[];
}

interface TreeNodeRequiredProps {
  level?: number;
  expanded?: boolean;
  selected?: boolean;
  checked?: boolean;
  halfChecked?: boolean;
  loaded?: boolean;
  loading?: boolean;
}

export interface TreeNodeProps extends TreeNodeRequiredProps {
  eventKey: Key;
  title: React.ReactNode | ((data: YmDataNode) => React.ReactNode);
  isStart: boolean[];
  isEnd: boolean[];
  data: YmDataNode;
}

export interface MotionTreeNodeProps extends TreeNodeProps {
  motion: motionConfig;
  motionNodes: InternalFlattenNode[] | null;
  motionType: 'show' | 'hide';
  onMotionEnd: () => void;
  expandedKeys: Key[];
  loadedKeys: Key[];
  loadingKeys: Key[];
  checkedKeys: Key[];
  halfCheckedKeys: Key[];
  selectedKeys: Key[];
  treeNodeRequiredProps: TreeNodeRequiredProps;
}
